//
//  CalendarModel.m
//  CarCare
//
//  Created by ileo on 14-8-4.
//  Copyright (c) 2014年 baozun. All rights reserved.
//

#import "CalendarMgr.h"

@interface CalendarMgr()

@property (nonatomic, strong) NSDateFormatter *formatter;

@property (nonatomic, strong) NSDateFormatter *formatterYear;
@property (nonatomic, strong) NSDateFormatter *formatterDay;
@property (nonatomic, strong) NSDateFormatter *formatterMonth;

@property (nonatomic, strong) NSCalendar *calendar;

@end

@implementation CalendarMgr
IMP_SINGLETON
- (instancetype)init
{
    self = [super init];
    if (self) {
        self.formatter = [[NSDateFormatter alloc] init];
        
        self.formatterDay = [[NSDateFormatter alloc] init];
        [self.formatterDay setDateFormat:@"dd"];
        
        self.formatterYear = [[NSDateFormatter alloc] init];
        [self.formatterYear setDateFormat:@"yyyy"];
        
        self.formatterMonth = [[NSDateFormatter alloc] init];
        [self.formatterMonth setDateFormat:@"MM"];
        
    }
    return self;
}

-(NSInteger)currentMonthDays{
    return [self daysInMonth:[self month] Year:[self year]];
}

-(NSInteger)yearWithDate:(NSDate *)date{
    return [[self.formatterYear stringFromDate:date] integerValue];
}

-(NSInteger)monthWithDate:(NSDate *)date{
    return [[self.formatterMonth stringFromDate:date] integerValue];
}

-(NSInteger)dayWithDate:(NSDate *)date{
    return [[self.formatterDay stringFromDate:date] integerValue];
}

-(NSDate *)dateWithStr:(NSString *)dateStr format:(NSString *)format{
    [self.formatter setDateFormat:format];
    return [self.formatter dateFromString:dateStr];
}

-(NSString *)dateStrWithDate:(NSDate *)date format:(NSString *)format{
    [self.formatter setDateFormat:format];
    return [self.formatter stringFromDate:date];
}

-(NSTimeInterval)timeIntervalWith_yyyy_MM_dd_Str:(NSString *)dateStr{
    NSDate *date = [CALENDARMGR dateWithStr:dateStr format:@"yyyy-MM-dd"];
    return [date timeIntervalSince1970];
}

+(NSDate *)dateFromDate:(NSDate *)date afterDays:(NSInteger)days{
    return [[NSDate alloc] initWithTimeInterval:days * 86400 sinceDate:date];
}

+(NSDate *)dateFromDate:(NSDate *)date beforeDays:(NSInteger)days{
    return [[NSDate alloc] initWithTimeInterval:days * -86400 sinceDate:date];
}

-(NSInteger)daysInYear:(NSInteger)year month:(NSInteger)month{
    return [self daysInMonth:month Year:year];
}

-(NSArray *)datesDayFrom:(NSDate *)from to:(NSDate *)to{
    
    NSMutableArray *arr = [NSMutableArray arrayWithCapacity:10];
    NSInteger startYear = [self yearWithDate:from];
    NSInteger startMonth = [self monthWithDate:from];
    NSInteger startDay = [self dayWithDate:from];
    NSInteger endYear = [self yearWithDate:to];
    NSInteger endMonth = [self monthWithDate:to];
    NSInteger endDay = [self dayWithDate:to];
    
    NSInteger mNum = [self daysInMonth:startMonth Year:startYear];
    
    for (NSInteger d = startDay, m = startMonth, y = startYear;
         y < endYear ||
         (y == endYear && m < endMonth) ||
         (y == endYear && m == endMonth && d <=endDay);
         d++) {
        
        [arr addObject:[NSString stringWithFormat:@"%zd-%02zd-%02zd",y,m,d]];
        
        if (d == mNum) {
            m += 1;
            if (m > 12) {
                m = 1;
                y += 1;
            }
            d = 0;
            mNum = [self daysInMonth:m Year:y];
        }
    }

    return arr;
}

-(NSArray *)datesMonthFrom:(NSDate *)from to:(NSDate *)to{
    NSMutableArray *arr = [NSMutableArray arrayWithCapacity:10];
    NSInteger startYear = [self yearWithDate:from];
    NSInteger startMonth = [self monthWithDate:from];
    NSInteger endYear = [self yearWithDate:to];
    NSInteger endMonth = [self monthWithDate:to];
    
    for (NSInteger m = startMonth, y = startYear;
         y < endYear ||
         (y == endYear && m < endMonth);
         m++) {
        
        [arr addObject:[NSString stringWithFormat:@"%zd-%02zd",y,m]];
        
        if (m == 12) {
            m = 0;
            y += 1;
        }
    }
    
    return arr;
}

#pragma mark - 

-(NSInteger)day{
    return [[self.formatterDay stringFromDate:[NSDate date]] integerValue];
}

-(NSInteger)month{
    return [[self.formatterMonth stringFromDate:[NSDate date]] integerValue];
}

-(NSInteger)year{
    return [[self.formatterYear stringFromDate:[NSDate date]] integerValue];
}

-(NSString *)currentDay{
    return [self dateStrWithDate:[NSDate date] format:@"yyyy-MM-dd"];
}

-(NSString *)nextDay{
    NSDate *next = [CalendarMgr dateFromDate:[NSDate date] afterDays:1];
    return [self dateStrWithDate:next format:yyyy_MM_dd];
}
-(NSString *)beforeDay
{
    NSDate *before = [CalendarMgr dateFromDate:[NSDate date] beforeDays:1];
    return [self dateStrWithDate:before format:yyyy_MM_dd];
}
-(NSInteger)daysInYear:(NSInteger)year{
    return (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) ? 366 : 365;
}

-(NSInteger)daysInMonth:(NSInteger)month Year:(NSInteger)year{
    if (month > 0 && month < 13) {
        switch (month) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                return 31;
                break;
            case 2:
                if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
                {
                    return 29;
                }
                else {
                    return 28;
                }
                break;
            default:
                return 30;
                break;
        }
    }
    return 0;
}

#pragma mark - 
-(DateModel *)today{
    if (!_today) {
        _today = [[DateModel alloc] init];
        _today.year = self.year;
        _today.month = self.month;
        _today.day = self.day;
    }
    return _today;
}

-(DateModel *)monthAfterDateModel:(DateModel *)from month:(NSInteger)months{
    NSInteger year = months / 12;
    NSInteger month = months % 12;
    DateModel *model = [[DateModel alloc] init];
    model.year = from.year + year;
    if (from.month + month > 12) {
        model.month = from.month + month - 12;
        model.year += 1;
    }else{
        model.month = from.month + month;
    }
    return model;
}

-(DateModel *)monthBeforeDateModel:(DateModel *)from months:(NSInteger)months{
    NSInteger year = months / 12;
    NSInteger month = months % 12;
    DateModel *model = [[DateModel alloc] init];
    model.year = from.year - year;
    if (from.month - month < 1) {
        model.month = 12 + from.month - month;
        model.year -= 1;
    }else{
        model.month = from.month - month;
    }
    return model;
}

-(DateModel *)monthBeforeDateModel:(DateModel *)from{
    DateModel *model = [[DateModel alloc] init];
    if (from.month == 1) {
        model.month = 12;
        model.year = from.year - 1;
    }else{
        model.month = from.month - 1;
        model.year = from.year;
    }
    return model;
}

-(DateModel *)monthAfterDateModel:(DateModel *)from{
    DateModel *model = [[DateModel alloc] init];
    if (from.month == 12) {
        model.month = 1;
        model.year = from.year + 1;
    }else{
        model.month = from.month + 1;
        model.year = from.year;
    }
    return model;
}

-(BOOL)dateModel:(DateModel *)a monthIsBeforeThanDateModel:(DateModel *)b{
    if (a.year == b.year) {
        return a.month < b.month;
    }else{
        return a.year < b.year;
    }
}


#pragma mark - calendar

+(NSCalendar *)calendar{
    return [NSCalendar currentCalendar];
}

+(BOOL)isSameDayWithDate1:(NSDate *)date1 date2:(NSDate *)date2{
    return [[CalendarMgr calendar] isDate:date1 inSameDayAsDate:date2];
}

+(BOOL)isSameMonthWithDate1:(NSDate *)date1 date2:(NSDate *)date2{
    return [[CalendarMgr calendar] isDate:date1 equalToDate:date2 toUnitGranularity:NSCalendarUnitMonth];
}

+(BOOL)isTodayWithDate:(NSDate *)date{
    return [[CalendarMgr calendar] isDateInToday:date];
}

+(BOOL)isDate1:(NSDate *)date1 laterThanDate2:(NSDate *)date2{
    return [date1 laterDate:date2] == date1;
}

+(NSDate *)firstDayInWeekForDate:(NSDate *)date{
    NSDate *day;
    if (![[CalendarMgr calendar] rangeOfUnit:NSCalendarUnitWeekOfMonth startDate:&day interval:NULL forDate:date]){
    }
    return day;
}

+(NSDate *)firstDayInLastWeekForDate:(NSDate *)date{
    NSDate *sunday = [CalendarMgr firstDayInWeekForDate:date];
    return [CalendarMgr dateFromDate:sunday beforeDays:7];
}

+(NSDate *)firstDayInNextWeekForDate:(NSDate *)date{
    NSDate *sunday = [CalendarMgr firstDayInWeekForDate:date];
    return [CalendarMgr dateFromDate:sunday afterDays:7];
}

+(NSDate *)firstDayInMonthForDate:(NSDate *)date{
    NSDate *firstDay;
    if (![[CalendarMgr calendar] rangeOfUnit:NSCalendarUnitMonth startDate:&firstDay interval:NULL forDate:date]){
    }
    return firstDay;
}

+(NSDate *)firstDayInLastMonthForDate:(NSDate *)date{
    NSDate *firstDay = [CalendarMgr firstDayInMonthForDate:date];
    return [CalendarMgr firstDayInMonthForDate:[CalendarMgr dateFromDate:firstDay beforeDays:1]];
}

+(NSDate *)firstDayInNextMonthForDate:(NSDate *)date{
    NSDate *firstDay = [CalendarMgr firstDayInMonthForDate:date];
    return [CalendarMgr firstDayInMonthForDate:[CalendarMgr dateFromDate:firstDay afterDays:31]];
}

+(NSInteger)weeksCountInMonthForDate:(NSDate *)date{
    NSRange range = [[CalendarMgr calendar] rangeOfUnit:NSCalendarUnitWeekOfMonth inUnit:NSCalendarUnitMonth forDate:date];
    return range.length;
}

+(NSInteger)daysCountInMonthForDate:(NSDate *)date{
    NSRange range = [[CalendarMgr calendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date];
    return range.length;
}

//从某天到某天间隔多少天
+(NSInteger)daysFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate
{
    if (fromDate && toDate) {
        NSDateComponents * dayComponents = [[CalendarMgr calendar]components:NSCalendarUnitDay fromDate:fromDate toDate:toDate options:0];
        return dayComponents.day;
    }
    return 0;
}

+(NSDateComponents *)componentsWithDate:(NSDate *)date{
    return [[CalendarMgr calendar] components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitWeekday|NSCalendarUnitWeekOfMonth|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond fromDate:date];
}

@end
